package org.etherframework.tests.features.mediator
{
	import org.etherframework.core.IModule;
	import org.etherframework.mediator.IMediators;
	import org.etherframework.tests.features.mediator.events.SomeEvent;
	import org.etherframework.tests.features.mediator.mediators.WeaklyDestroyableMediator;
	import org.etherframework.tests.features.mediator.views.TrivialView;
	import org.etherframework.tests.utils.ModuleInfo;
	import org.etherframework.tests.utils.TestUtility;
	import org.flexunit.async.Async;
	import org.fluint.uiImpersonation.UIImpersonator;
	import org.hamcrest.assertThat;
	import org.hamcrest.object.equalTo;
	import org.hamcrest.object.isFalse;
	import org.hamcrest.object.isTrue;
	
	import spark.components.Group;

	public class when_using_weak_mediator
	{	
		private static var _testUtility:TestUtility = new TestUtility();
		private static var _module:IModule;
		private static var _weaklyDestroyableMediator:WeaklyDestroyableMediator;
		private static var _m:IMediators;
		private static var _moduleView:Group;
		private static var _info:ModuleInfo;
		private static var _view:TrivialView;
		
		[BeforeClass(async)]
		public static function setUpBeforeClass():void
		{
			_moduleView = UIImpersonator.addChild(new Group()) as Group;
			_info = _testUtility.createModuleInfo(null, _moduleView);
			_module = _info.module;
			_m = _module.mediators;
			_view = new TrivialView();
			
			_m.addMediator(TrivialView, WeaklyDestroyableMediator);
			
			_moduleView.addElement(_view);
			_weaklyDestroyableMediator = _m.hasMediator(_view) as WeaklyDestroyableMediator;
			
			Async.delayCall(when_using_weak_mediator, function():void{}, 100);
		}
		
		[AfterClass]
		public static function tearDownAfterClass():void
		{
			_testUtility.dispose();
			UIImpersonator.removeAllChildren();
		}
		
		[Test(order=1)]
		public function mediator_should_be_attached():void
		{
			// Arrange
			
			// Act
			
			// Assert
			assertThat(_weaklyDestroyableMediator.detached, isFalse());
			assertThat(_weaklyDestroyableMediator.destroyed, isFalse());
			assertThat(_weaklyDestroyableMediator.initCounter, equalTo(1));
			assertThat(_weaklyDestroyableMediator.completeCounter, equalTo(1));
		}
		
		[Test(order=2)]
		public function mediator_should_respond_to_events_when_attached():void
		{
			// Arrange
			
			// Act
			_module.ether.dispatch(new SomeEvent(SomeEvent.SOME));
			
			// Assert
			assertThat(_weaklyDestroyableMediator.eventCounter, equalTo(1));
		}
		
		[Test(order=3, async)]
		public function mediator_should_be_detached_when_removed_view_from_stage():void
		{
			// Arrange
			
			// Act
			_moduleView.removeElement(_view);
			
			// Assert
			Async.delayCall(this, function():void
			{
				assertThat(_weaklyDestroyableMediator.detached, isTrue()); 
				assertThat(_weaklyDestroyableMediator.destroyed, isFalse());
				assertThat(_weaklyDestroyableMediator.initCounter, equalTo(1));
				assertThat(_weaklyDestroyableMediator.completeCounter, equalTo(1));
				assertThat(_weaklyDestroyableMediator.eventCounter, equalTo(1));
			}, 100);
		}
		
		[Test(order=4)]
		public function mediator_should_not_respond_to_events_when_detached():void
		{
			// Arrange
			
			// Act
			_module.ether.dispatch(new SomeEvent(SomeEvent.SOME));
			
			// Assert
			assertThat(_weaklyDestroyableMediator.eventCounter, equalTo(1));
		}
		
		[Test(order=5, async)]
		public function mediator_should_be_attached_when_added_view_to_stage():void
		{
			// Arrange
			
			// Act
			_moduleView.addElement(_view);
			
			// Assert
			Async.delayCall(this, function():void
			{
				assertThat(_weaklyDestroyableMediator.detached, isFalse()); 
				assertThat(_weaklyDestroyableMediator.destroyed, isFalse());
				assertThat(_weaklyDestroyableMediator.initCounter, equalTo(1));
				assertThat(_weaklyDestroyableMediator.completeCounter, equalTo(1));
			}, 100);
		}
		
		[Test(order=6)]
		public function mediator_should_respond_to_events_when_attached_once_again():void
		{
			// Arrange
			
			// Act
			_module.ether.dispatch(new SomeEvent(SomeEvent.SOME));
			
			// Assert
			assertThat(_weaklyDestroyableMediator.eventCounter, equalTo(2));
		}
	}
}